package main

import (
	"path/filepath"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/driver/desktop"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
	"gitee.com/y2h/fyneExplorer/me"
)

const (
	fileIconSize       = 64
	fileInlineIconSize = 24
	fileIconCellWidth  = fileIconSize * 1.25
)

type fileDialogItem struct {
	widget.BaseWidget
	picker *fileDialog

	id       int
	name     string
	location fyne.URI
	// 是否是（父parent）目录
	dir                              bool
	iconDelete, iconRename, iconView *me.ClickIcon
}

func (i *fileDialogItem) Tapped(*fyne.PointEvent) {
	i.Select()
}
func (i *fileDialogItem) DoubleTapped(*fyne.PointEvent) {
	// if listable, err := storage.CanList(i.location); err == nil && listable {
	if i.dir {
		i.picker.setLocation(i.location)
		return
	}
	i.Select()
	me.ViewFile(i.location.Path(), i.picker.dir)
	// i.Tapped(nil)
}
func (i *fileDialogItem) TappedSecondary(e *fyne.PointEvent) {
	i.Select()
	me.MenuRight.ShowAtPosition(e.AbsolutePosition)
}
func (i *fileDialogItem) MouseIn(*desktop.MouseEvent) {
	if !i.dir {
		i.iconDelete.Show()
		i.iconRename.Show()
		i.iconView.Show()
		i.Refresh()
	}
}

// MouseMoved is called when a desktop pointer hovers over the widget
func (i *fileDialogItem) MouseMoved(*desktop.MouseEvent) {
}

// MouseOut is called when a desktop pointer exits the widget
func (i *fileDialogItem) MouseOut() {
	i.iconDelete.Hide()
	i.iconRename.Hide()
	i.iconView.Hide()
	i.Refresh()
}

func (i *fileDialogItem) Select() {
	i.picker.files.Select(i.id)
}

func (i *fileDialogItem) CreateRenderer() fyne.WidgetRenderer {
	text := widget.NewLabelWithStyle(i.name, fyne.TextAlignCenter, fyne.TextStyle{})
	text.Truncation = fyne.TextTruncateEllipsis
	text.Wrapping = fyne.TextWrapBreak
	icon := widget.NewFileIcon(i.location)
	i.iconDelete = me.NewClickIcon(me.ResDelete, func() {
		i.Select()
		i.picker.Delete()
	})
	i.iconRename = me.NewClickIcon(me.ResRename, func() {
		i.Select()
		i.picker.Rename()
	})
	i.iconView = me.NewClickIcon(me.ResView, func() {
		me.ViewFile(i.location.Path(), i.picker.dir)
	})
	i.iconDelete.Hide()
	i.iconRename.Hide()
	i.iconView.Hide()
	return &fileItemRenderer{
		item:         i,
		icon:         icon,
		text:         text,
		objects:      []fyne.CanvasObject{icon, text, i.iconDelete, i.iconRename, i.iconView},
		fileTextSize: widget.NewLabel("M\nM").MinSize().Height, // cache two-line label height,
	}
}

func (i *fileDialogItem) setLocation(l fyne.URI, dir, up bool) {
	i.dir = dir
	i.location = l
	i.name = l.Name()

	if i.picker.view == gridView {
		ext := filepath.Ext(i.name[1:])
		i.name = i.name[:len(i.name)-len(ext)]
	}

	if up {
		i.name = "(Parent)"
	}

	i.Refresh()
}

func (f *fileDialog) newFileItem(location fyne.URI, dir, up bool) *fileDialogItem {
	item := &fileDialogItem{
		picker:   f,
		location: location,
		name:     location.Name(),
		dir:      dir,
	}

	if f.view == gridView {
		ext := filepath.Ext(item.name[1:])
		item.name = item.name[:len(item.name)-len(ext)]
	}

	if up {
		item.name = "(Parent)"
	}

	item.ExtendBaseWidget(item)
	return item
}

type fileItemRenderer struct {
	item         *fileDialogItem
	fileTextSize float32

	icon    *widget.FileIcon
	text    *widget.Label
	objects []fyne.CanvasObject
}

func (s *fileItemRenderer) Layout(size fyne.Size) {
	if s.item.picker.view == gridView {
		s.icon.Resize(fyne.NewSize(fileIconSize, fileIconSize))
		s.icon.Move(fyne.NewPos((size.Width-fileIconSize)/2, 0))

		s.text.Alignment = fyne.TextAlignCenter
		s.text.Resize(fyne.NewSize(size.Width, s.fileTextSize))
		s.text.Move(fyne.NewPos(0, size.Height-s.fileTextSize))
		w := size.Width / 3
		s.item.iconView.Resize(fyne.NewSquareSize(w))
		s.item.iconView.Move(fyne.NewSquareOffsetPos(2))
		s.item.iconRename.Resize(fyne.NewSquareSize(w))
		s.item.iconRename.Move(fyne.NewPos(2, w+1))
		s.item.iconDelete.Resize(fyne.NewSquareSize(w))
		s.item.iconDelete.Move(fyne.NewPos(2, 2*w+1))
	} else {
		s.icon.Resize(fyne.NewSize(fileInlineIconSize, fileInlineIconSize))
		s.icon.Move(fyne.NewPos(s.icon.Size().Width*3+theme.Padding(), (size.Height-fileInlineIconSize)/2))
		s.text.Alignment = fyne.TextAlignLeading
		textMin := s.text.MinSize()
		s.text.Resize(fyne.NewSize(size.Width, textMin.Height))
		s.text.Move(fyne.NewPos(s.icon.Size().Width*4+fileInlineIconSize, (size.Height-textMin.Height)/2))

		s.item.iconView.Resize(s.icon.Size())
		s.item.iconView.Move(fyne.NewSquareOffsetPos((size.Height - fileInlineIconSize) / 2))
		s.item.iconRename.Resize(s.icon.Size())
		s.item.iconRename.Move(fyne.NewPos(s.icon.Size().Width+theme.Padding(), (size.Height-fileInlineIconSize)/2))
		s.item.iconDelete.Resize(s.icon.Size())
		s.item.iconDelete.Move(fyne.NewPos(s.icon.Size().Width*2+theme.Padding(), (size.Height-fileInlineIconSize)/2))
	}
	s.text.Refresh()
}

func (s *fileItemRenderer) MinSize() fyne.Size {
	if s.item.picker.view == gridView {
		return fyne.NewSize(fileIconCellWidth, fileIconSize+s.fileTextSize)
	}

	textMin := s.text.MinSize()
	return fyne.NewSize(fileInlineIconSize+textMin.Width+theme.Padding(), textMin.Height)
}

func (s *fileItemRenderer) Refresh() {
	s.fileTextSize = widget.NewLabel("M\nM").MinSize().Height // cache two-line label height

	s.text.SetText(s.item.name)
	s.icon.SetURI(s.item.location)
}

func (s *fileItemRenderer) Objects() []fyne.CanvasObject {
	return s.objects
}

func (s *fileItemRenderer) Destroy() {
}
